package com.bo.redis.limit;

import java.util.LinkedList;

/**
 * 时间窗口滑动限流
 *
 * @Author: gpb
 * @Date: 2025/2/3 21:02
 * @Description:
 */
public class SlidingTimeWindowLimiter implements TrafficLimiter {

    private int reqCount = 0; // 请求计数器
    private LinkedList<Integer> window = new LinkedList<>();// 窗口队列
    private int limitNum = 100; // 限制数量
    private long windowLength = 100L; // 窗口长度
    private int windowNum = 10; // 窗口数量

    @Override
    public synchronized boolean limit() {
        if (reqCount + 1 > limitNum) {
            // 超过限制数量，返回true
            return true;
        }
        // 最后一个窗口数量+1
        window.set(window.size() - 1, window.peekLast() + 1);
        // 总数加1
        reqCount++;
        return false;
    }

    public SlidingTimeWindowLimiter() {
        // 初始化窗口队列
        window.addLast(0);
        // 启动一个线程，每秒更新窗口队列
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(windowLength);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (this) {
                    // 添加一个窗口，并删除第一个窗口
                    // 滑动窗口
                    window.addLast(0);
                    if (window.size() > windowNum) {
                        reqCount -= window.peekFirst();
                        window.removeFirst();
                    }
                }
            }
        }).start();
    }

}
